package demo.util;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * java8 线程安全的时间工具类，用于替代java.util.Date类
 *
 * @author hanjy
 */
public class DateTimeUtils {

    private DateTimeUtils() {
        // to prevent instantiation of this class
    }

    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 获取时间部分
     *
     * @param date
     *            HH:mm:ss
     * @return
     */
    public static LocalTime parseTime(String date, DateTimeFormatter formatter) {
        if (date == null || date.isEmpty()) {
            return null;
        }
        return LocalTime.parse(date, formatter);
    }

    /**
     * 获取日期和时间部分
     *
     * @param date
     *            yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static LocalDateTime parseDateTime(String date, DateTimeFormatter formatter) {
        if (date == null || date.isEmpty()) {
            return null;
        }
        return LocalDateTime.parse(date, formatter);
    }

    /**
     * 获取日期部分
     *
     * @param date
     *            yyyy-MM-dd
     * @return
     */
    public static LocalDate parseDate(String date, DateTimeFormatter formatter) {
        if (date == null || date.isEmpty()) {
            return null;
        }
        return LocalDate.parse(date, formatter);
    }

    /**
     * LocalDateTime 转Date
     *
     * @param localDateTime
     * @return
     */
    public static Date from(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        Instant instant = localDateTime.toInstant(ZoneOffset.of("+8"));
        return Date.from(instant);
    }

    /**
     * 相差多少天
     *
     * @param start
     * @param end
     * @return
     */
    public static long untilByDays(LocalDate start, LocalDate end) {
        return start.until(end, ChronoUnit.DAYS);
    }

    /**
     * 到现在相差多少天
     *
     * @param localDate
     * @return
     */
    public static long untilNowByDay(LocalDate localDate) {
        return untilByDays(localDate, LocalDate.now());
    }

    /**
     * 时间戳转时间
     *
     * @param epochMilli
     * @return
     */
    public static LocalDateTime toLocalDateTime(long epochMilli) {
        Instant instant = Instant.ofEpochMilli(epochMilli);
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.of("+8"));
        return offsetDateTime.toLocalDateTime();
    }

    /**
     * 判断两个时间戳是否属于同一天
     * 
     * @param d1
     * @param d2
     * @return
     */
    public static boolean isSameDay(Date d1, Date d2) {
        if (d1 == d2) {
            return true;
        }
        if (d1 == null && d2 != null || d1 != null && d2 == null) {
            return false;
        }
        if (d1.getTime() == d2.getTime()) {
            return true;
        }
        LocalDate dt1 = toLocalDateTime(d1.getTime()).toLocalDate();
        LocalDate dt2 = toLocalDateTime(d2.getTime()).toLocalDate();
        return dt1.equals(dt2);
    }

    public static void main(String[] args) {
        long t = System.currentTimeMillis();
        System.out.println(isSameDay(null, null));
        System.out.println(isSameDay(new Date(), null));
        System.out.println(isSameDay(null, new Date()));
        System.out.println(isSameDay(new Date(), new Date(t)));
        System.out.println(isSameDay(new Date(), new Date(t - 24 * 3600 * 1000)));
    }

}
